#pragma once

#ifndef MAINVIEW_H_
#define MAINVIEW_H_

#include <gtksourceviewmm.h>
#include <gtkmm.h>

namespace coder
{

class SourceEditorView : public gtksourceview::SourceView
{
public:
    class Controller
    {
    public:
        virtual void onMenuFileSave() = 0;
    };
    
protected:
    Controller * _controller;
public:
    SourceEditorView(Controller * controller)
        :_controller(controller){}

protected:
    virtual void on_populate_popup(Gtk::Menu * menu)
    {
        gtksourceview::SourceView::on_populate_popup(menu);

        Gtk::Menu::MenuList & menulist = menu->items();

        menulist.insert(menulist.begin(), Gtk::Menu_Helpers::SeparatorElem());
        menulist.insert(menulist.begin(), 
                        Gtk::Menu_Helpers::StockMenuElem(
                              Gtk::StockID("gtk-save"), sigc::mem_fun(*this, &SourceEditorView::on_context_save)));
    }

    void on_context_save()
    {
        _controller->onMenuFileSave();
    }
};

class MainView : public Gtk::Window, 
                 public SourceEditorView::Controller
{
private:
	Glib::RefPtr<Gtk::UIManager>   _refUIManager;
  	Glib::RefPtr<Gtk::ActionGroup> _refActionGroup;
  	Gtk::Menu                    * _pMenuPopup;
	Glib::RefPtr<gtksourceview::SourceBuffer> 
	                               _source_buffer;
	SourceEditorView               _sourceView;
	Gtk::ScrolledWindow            _scrolledWindow;
  	IEventsHandler               * _eventsHandler;
	
public:
	MainView()
	    :_sourceView(this)
	{
		gtksourceview::init();

	   	Glib::RefPtr<gtksourceview::SourceLanguageManager> lang_manager = 
	   							gtksourceview::SourceLanguageManager::create();
	    
		Glib::RefPtr<gtksourceview::SourceLanguage> lang;
		lang  =	lang_manager->get_language("cpp");
		 
		_source_buffer = gtksourceview::SourceBuffer::create(lang);
	}

	void setEventsHandler(IEventsHandler * eventsHandler)
	{
		_eventsHandler = eventsHandler;
	}

    void onMenuFileSave()
    {
        on_save_event();
    }
    
	bool key_pressed(GdkEventKey *event)
	{
		switch (event->keyval)
		{
			case 0x73://ctrl+s
		        on_save_event();
		        break;
		   default:
		        break;
		}      
		return false;
	}

	void initialize()
	{
		signal_key_press_event().connect(sigc::mem_fun(*this, &MainView::key_pressed));

		_sourceView.set_buffer(_source_buffer);
		
		Pango::FontDescription font("monospace");
		
		_sourceView.modify_font(font);
		
		set_border_width( 4 );
		set_default_size( 600, 400 );
		
		_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
		_scrolledWindow.show();
		_scrolledWindow.add(_sourceView);
		
		add( _scrolledWindow );
		
		_source_buffer->set_highlight_syntax(true);
		_sourceView.set_tab_width(4);
		_sourceView.set_auto_indent(true);
		_sourceView.set_insert_spaces_instead_of_tabs(true);
		_sourceView.set_show_line_numbers(true);
		_sourceView.set_smart_home_end(gtksourceview::SOURCE_SMART_HOME_END_ALWAYS);
		
		_sourceView.show();
		set_position(Gtk::WIN_POS_CENTER);
	}
	
	void updateBuffer(const std::string & text)
	{
		_source_buffer->set_text(text);
		Gtk::TextBuffer::iterator iter =
		        _source_buffer->get_iter_at_line(0) ;
		
	    _source_buffer->place_cursor(iter) ;
	}
	
	std::string getBuffer()
	{
		return _source_buffer->get_text();
	}
private:
	void on_save_event()
	{
		_eventsHandler->handle(ApplicationEvent("save"));
	}
};

}

#endif /*MAINVIEW_H_*/
